package com.rec.smile.rpc.provider.codec;

import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.sf.cglib.reflect.FastClass;
import net.sf.cglib.reflect.FastMethod;

import com.rec.smile.rpc.api.RpcRequest;
import com.rec.smile.rpc.api.RpcResponse;

public class RpcHandler extends SimpleChannelInboundHandler<RpcRequest> {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(RpcHandler.class);
	
	
	private Map<String, Object> handermap;
	
	public RpcHandler(Map<String, Object> handermap) {
		super();
		this.handermap = handermap;
	}



	@Override
	protected void channelRead0(ChannelHandlerContext ctx, RpcRequest msg)
			throws Exception {
		RpcResponse rpcResponse = new RpcResponse();
		rpcResponse.setRequestId(msg.getRequestId());
		try {
			rpcResponse.setResult(handlerMsg(msg));
		} catch (Exception e) {
			rpcResponse.setError(e);
		}
		
		ctx.writeAndFlush(rpcResponse).addListener(ChannelFutureListener.CLOSE);
	}



	private Object handlerMsg(RpcRequest msg) throws Exception {
		Object serviceBean = handermap.get(msg.getClassName());
		FastClass serviceFastClass = FastClass.create(serviceBean.getClass());
        FastMethod serviceFastMethod = serviceFastClass.getMethod(msg.getMethodName(), msg.getParameterTypes());
        return serviceFastMethod.invoke(serviceBean, msg.getParameters());
	}



	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
			throws Exception {
		LOGGER.error("server catught exception", cause);
		ctx.close();
	}
	
	

}
